package com.example.demo.impl;

import com.example.demo.entity.Order;
import com.example.demo.entity.Taco;
import com.example.demo.service.OrderRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class JdbcOrderRepository implements OrderRepository {

    //SimpleJdbcInsert对JdbcTemplate进行了封装
    private SimpleJdbcInsert orderInsert;
    private SimpleJdbcInsert orderTacoInsert;
    private ObjectMapper objectMapper;


    @Autowired
    public JdbcOrderRepository(JdbcTemplate jdbc) {
        this.orderInsert = new SimpleJdbcInsert(jdbc)
                .withTableName("Taco_Order")   //配置为何Taco_Order表协作
                .usingGeneratedKeyColumns("id");  // 假定 id 是由数据库提供
        this.orderTacoInsert = new SimpleJdbcInsert(jdbc)
                .withTableName("Taco_Order_Tacos");
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public Order save(Order order) {
        order.setPlaceAt(new Date());
        long orderId = saveOrderDetails(order);
        order.setId(orderId);
        List<Taco> tacos = order.getTacos();
        for (Taco taco : tacos) {
            saveTacoToOrder(taco, orderId);
        }
        return order;
    }
    /*
      SimpleJdbcInsert 有两个方法可以插入数据 execute()和executeAndReturnKey(),他们都接受Map<String,Object>作为参数
      其中key对应表中要插入的列名，value对应实际插入表中的数据
     */

    private long saveOrderDetails(Order order) {
        @SuppressWarnings("unchecked")
        Map<String, Object> values = objectMapper.convertValue(order, Map.class); //把对象转换成一个map
        values.put("placedAt", order.getPlaceAt());
        long orderId = orderInsert.executeAndReturnKey(values)
                .longValue(); //返回id
        return orderId;
    }


    private void saveTacoToOrder(Taco taco, long orderId) {
        Map<String, Object> values = new HashMap<>();
        values.put("tacoOrder", orderId);
        values.put("taco", taco.getId());
        orderTacoInsert.execute(values);
    }
}
